{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# VIRTUAL PEN USING OPENCV PYTHON"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "code description is available in medium \n",
    "<a href=\"https://medium.com/programming-fever\">@programmimg_fever</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#programming_fever\n",
    "import cv2\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "load_from_disk = True\n",
    "if load_from_disk:\n",
    "    hsv_value = np.load('hsv_value.npy')\n",
    "\n",
    "cap = cv2.VideoCapture(0)\n",
    "cap.set(3,1280)\n",
    "cap.set(4,720)\n",
    "\n",
    "kernel = np.ones((5,5),np.uint8)\n",
    "\n",
    "# Initializing the canvas on which we will draw upon\n",
    "canvas = None\n",
    "\n",
    "# Initilize x1,y1 points\n",
    "x1,y1=0,0\n",
    "\n",
    "# Threshold for noise\n",
    "noiseth = 800\n",
    "\n",
    "while(1):\n",
    "    _, frame = cap.read()\n",
    "    frame = cv2.flip( frame, 1 )\n",
    "    \n",
    "    # Initialize the canvas as a black image of the same size as the frame.\n",
    "    if canvas is None:\n",
    "        canvas = np.zeros_like(frame)\n",
    "\n",
    "    # Convert BGR to HSV\n",
    "    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)\n",
    "    \n",
    "    # If you're reading from memory then load the upper and lower ranges \n",
    "    # from there\n",
    "    if load_from_disk:\n",
    "        lower_range = hsv_value[0]\n",
    "        upper_range = hsv_value[1]\n",
    "            \n",
    "    # Otherwise define your own custom values for upper and lower range.\n",
    "    else:           \n",
    "        lower_range  = np.array([134, 20, 204])\n",
    "        upper_range = np.array([179, 255, 255])\n",
    "    \n",
    "    mask = cv2.inRange(hsv, lower_range, upper_range)\n",
    "    \n",
    "    # Perform morphological operations to get rid of the noise\n",
    "    mask = cv2.erode(mask,kernel,iterations = 1)\n",
    "    mask = cv2.dilate(mask,kernel,iterations = 2)\n",
    "    \n",
    "    # Find Contours\n",
    "    contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "    \n",
    "    # Make sure there is a contour present and also its size is bigger than \n",
    "    # the noise threshold.\n",
    "    if contours and cv2.contourArea(max(contours, \n",
    "                                 key = cv2.contourArea)) > noiseth:\n",
    "                \n",
    "        c = max(contours, key = cv2.contourArea)    \n",
    "        x2,y2,w,h = cv2.boundingRect(c)\n",
    "        \n",
    "        # If there were no previous points then save the detected x2,y2 \n",
    "        # coordinates as x1,y1. \n",
    "        # This is true when we writing for the first time or when writing \n",
    "        # again when the pen had disappeared from view.\n",
    "        if x1 == 0 and y1 == 0:\n",
    "            x1,y1= x2,y2\n",
    "            \n",
    "        else:\n",
    "            # Draw the line on the canvas\n",
    "            canvas = cv2.line(canvas, (x1,y1),(x2,y2), [255,0,0], 4)\n",
    "        \n",
    "        # After the line is drawn the new points become the previous points.\n",
    "        x1,y1= x2,y2\n",
    "\n",
    "    else:\n",
    "        # If there were no contours detected then make x1,y1 = 0\n",
    "        x1,y1 =0,0\n",
    "    \n",
    "    # Merge the canvas and the frame.\n",
    "    frame = cv2.add(frame,canvas)\n",
    "    \n",
    "    # Optionally stack both frames and show it.\n",
    "    stacked = np.hstack((canvas,frame))\n",
    "    cv2.imshow('VIRTUAL PEN',cv2.resize(stacked,None,fx=0.6,fy=0.6))\n",
    "\n",
    "    k = cv2.waitKey(1) & 0xFF\n",
    "    if k == 27:\n",
    "        break\n",
    "        \n",
    "    # When c is pressed clear the canvas\n",
    "    if k == ord('c'):\n",
    "        canvas = None\n",
    "\n",
    "cv2.destroyAllWindows()\n",
    "cap.release()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# FB Page\n",
    "<a href=\"https://www.facebook.com/GeekyPRAVEE\">@programmimg_fever</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# GitHub link\n",
    "<a href=\"https://github.com/GeekyPRAVEE\">@programmimg_fever</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Twitter \n",
    "<a href=\"https://twitter.com/GeekyPRAVEE\">@programmimg_fever</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# follow on insta\n",
    "<a href=\"https://www.instagram.com/programming_fever/\">@programmimg_fever</a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
